import React from 'react';
import { message, Alert, Spin } from 'antd';
import { WeaLocaleProvider, WeaNewScroll } from 'ecCom';
import WeaDocFileItem from './fileItem';
import WeaDocNoData from '../noData';
import { getRandomString, judgeBrowserType, onDelegate, offDelegate } from '../../../util';


const getLabel = WeaLocaleProvider.getLabel;

/*
* 属性：
*  data                数据 array【数据结构如下】
*  iconType            文件图标的展示类型 string 【默认值："svg"。 可选值："svg": 使用系统规范的svg图标，"img"：使用自定义的图片】
*
*  editable            是否可编辑文件名 boolean  【默认值：false】
*  editMode            编辑模式(开始编辑、确认编辑、取消编辑的方式) number【默认值：0】可选值：0,1。0表示点击图标开始编辑，按钮+enter键确认取消; 1表示点击文本开始编辑，点击其他区域终止编辑
*  isEditingSameTime   是否允许同时编辑多个文件/文件夹的名称 boolean 【默认值: true】
*  namingRules         命名规则 string【默认值 "default"仅清除两端空格。可选值："compatible"兼容Windows、Mac、Linux的命名规则; "none"没有任何规则】会影响onOK事件和onChange事件(onChange返回值不受阻拦)
*  editStart           点击编辑按钮的回调 【参数：id  返回值：false阻止编辑，true允许编辑】
*  onChange            编辑文本框的onchange回调【参数： key:当前编辑的数据id, val:编辑框内的值{ fullName, name, ext }。返回值(非必需)：string设定编辑框中显示的文本】如果没有特殊需求，不建议使用onChange受控，确认和取消的逻辑需要做额外处理
*  onOk                确认编辑的点击事件 【参数：key:编辑的数据id, val:编辑框内的值{ fullName, name, ext }。返回值：返回true表示编辑完成，返回false表示不能结束编辑】
*  onCancel            取消编辑的点击事件 【参数：key:编辑的数据id】
*
*  selectable          是否开启选择 boolean 【默认值：false】
*  rightSelect         是否右键选择 boolean 【默认值：false】
*  irrelevantArea      点击无关区域，清空所有选中(左右键通用，无关区域的范围：WeaDocument-FileIconView元素) boolean 【默认值：true】
*  onSelect            选中事件的回调 【参数：keys:[array]最新的选中ids; current:[object]当前操作的key,及操作前的选中状态 】
*  selectedKeys        被选中的文件/夹ids  array
*  selectMode          要开启的选择模式？ number 【默认：0.无任何附加功能的选择  1.左键:单击单选、ctrl+单击多选;右键:与windows一样的逻辑】
*
*  collectable         是否启用收藏 boolean【默认值：false】
*  onFav               点击收藏图标的事件回调
*  onClick             点击整个Item组件的事件回调【参数：id, e】
*  onDoubleClick       点击整个Item组件的双击事件回调【参数：id, e】
*
*  titleType           鼠标悬浮title效果【string 可选值：none、default、toolTip 】分别是：无、原生title、组件提供的title
*  titlePosition       title框与鼠标的相对位置【object】仅在toolTip时有效，默认：{ icon: { x: 10, y: 17 }, name: { x: 7, y: 12 } }
*  textCharLen         标题多行文本溢出的兼容性方案：限制文本字符长度 【number】说明：textCharLen和textByteLen对webkit内核不生效，确切地说，对一些不那么老的非webkit内核也不生效，只有当浏览器版本很老时，作为一个兜底方案。
*  textByteLen         标题多行文本溢出的兼容性方案：限制文本字节长度 【number 默认：23】说明：textCharLen和textByteLen互斥，二者用其一，如果两者都传值，优先使用textCharLen。两者都不传值，默认使用textByteLen
*
*  draggable           是否允许拖拽？【boolean 默认值false】（此处的拖拽功能：将文件拖动到文件夹中，文件的移动）【不支持IE】
*  dragSuccess         拖拽成功的回调【function】【参数：to ,keys。分别为目标目录id、被拖动文件的ids】
*
*  scrollHeight        滚动条高度【非必填 number】不传参将默认适应组件高度(需要设定组件高度)
*  loadMore            是否滚动加载更多【boolean 默认值：false】
*  pageLoading         分页加载的loading效果 boolean 【默认：false】
*  pageEnd             是否全部加载完毕 boolean 【默认: false】
*  onScroll            滚动事件 function 【非必填 参数：e】
*  onScrollTop         滚动到顶端的事件(从下往上滚动才会触发) function 【非必填 参数：e, type: 表示触发此回调的行为"up" or "top"：前者表示在设置offsetTop后，从下往上滚动到指定位置时触发; 后者表示已滚动到顶端后，继续向上滑动滚轮的行为】
*  onScrollEnd         滚动到底部的事件(从上往下滚动才会触发) function 【非必填 参数：e, type: 表示触发此回调的行为"down" or "bottom"：前者表示在设置offsetBottom后，从上往下滚动到指定位置时触发; 后者表示没有滚动条或已经滚动到底端后，继续向下滑动滚轮的行为】
*  wheelAssist         是否需要鼠标滚轮事件的辅助 boolean 【默认false。何时使用？当页面内容少，没有出现滚动条，却仍想监听上下滚动事件时】会影响onScrollTop和onScrollEnd事件
*  offsetTop           与顶部的偏差，距离顶部多少距离执行onScrollTop number 【默认：0】
*  offsetBottom        与底部的偏差，距离底部多少距离执行onScrollEnd number 【默认：0，滚动加载建议：30】
*
*  className           <IconView />组件的className
*  style               <IconView />组件的style
*  scrollInnerClass    <IconView />组件滚动部分父元素className
*  scrollInnerStyle    <IconView />组件滚动部分父元素style
*  itemClass           Item组件的className
*  itemStyle           Item组件的style
*
*
* 方法：【通过ref调用】
*  newFolder()          新建文件夹【返回值：最新的元数据】
*  reNameFile()         重命名(本质上是模拟点击)【参数：id】
*
* 数据结构：
*  data: [{
*     id             【必需】
*     type           类型：file or folder【必需】
*     textname       名称【必需】
*
*     isFav          是否已收藏
*
*     editable        是否可编辑文件名【注意；这里的配置会覆盖editable属性的配置】
*     editing         是否正在编辑【仅在初始状态有效】
*     selectable      是否开启选择【注意；这里的配置会覆盖selectable属性的配置】
*     rightSelect     是否右键选择【这里的配置会覆盖rightSelect属性的配置】
*     selected        是否被选中
*
*     titleText: {
*        icon: "名称：123.txt<br/>大小：321KB",    // 悬浮在图标上的显示文本,支持html转义
*        name: "123.txt",                         // 悬浮在文件名上的显示文本,支持html转义
*     }
*     ctrlX           是否被ctrl+x剪切了
*  },
*  ......
* ]
*
* 说明：
*  1.新建文件夹时，取消新建功能。其实就是点击取消按钮，需要借助onCancel事件，操作数据即可
*
* */


class WeaDocFileIconView extends React.Component {
   static defaultProps = {
      iconType: 'svg',
      editMode: 0,
      namingRules: 'default',
      isEditingSameTime: true,
      editStart: null,
      onOk: null,
      onCancel: null,
      onChange: null,
      onFav: null,
      onClick: null,
      onDoubleClick: null,
      selectable: false,
      irrelevantArea: true,
      selectedKeys: [],
      selectMode: 0,
      rightSelect: false,
      titleType: 'none',
      textCharLen: null,
      textByteLen: 23,
      draggable: false,
      dragSuccess: null,
      loadMore: false,
      pageLoading: false,
      pageEnd: false,
      offsetTop: 0,
      offsetBottom: 0,
      wheelAssist: false,
      onScroll: null,
      onScrollTop: null,
      onScrollEnd: null,
   };

   constructor(props) {
      super(props);
      this.ChildrenRefs = {}; // 子组件的ref
      this.scroll = {
         prevScroll: 0,
         prevBottom: false,
         prevTop: true,
      }; // 滚动相关
      this.ItemData = {}; // 为子组件提供暂存数据的地方
      this.browser = judgeBrowserType(); this.browser.version = parseFloat(this.browser.version); // 判断浏览器类型
      this.dragSupport = this.browserCompatible(this.browser); // 判断浏览器是否支持拖拽API
      this.font = { isExtra: null, isObserver: null }; // 字体大小相关
      this.state = {
         selectedKeys: {},
         editing: false,
         fontClass: this.initFontHandle(), // 初始化字体处理,
      };

      console.log('mount', navigator.userAgent, this.browser);
   }

   static getDerivedStateFromProps(nextProps) {
      // 转化SelectedKeys: array -> object
      let newSelect = {};
      nextProps.selectedKeys.forEach((i) => {
 newSelect[i] = true; 
});
      return { selectedKeys: newSelect };
   }

   componentDidMount() {
      const { selectable, rightSelect, irrelevantArea, wheelAssist } = this.props;
      // selectable && irrelevantArea && this.mainDom.addEventListener("click", this.clearSelection);
      // selectable && irrelevantArea && rightSelect && this.mainDom.addEventListener("contextmenu", this.clearSelection);
      selectable && irrelevantArea && onDelegate('click', this.mainDom, '.WeaDoc-FileViewItem', this.clearSelection, {}, true);
      selectable && irrelevantArea && rightSelect && onDelegate('contextmenu', this.mainDom, '.WeaDoc-FileViewItem', this.clearSelection, {}, true);
      wheelAssist && this.InnerScroll.addEventListener('wheel', this.mouseWheelHandle);
   }

   componentWillUnmount() {
      const { selectable, rightSelect, irrelevantArea, wheelAssist } = this.props;
      selectable && irrelevantArea && offDelegate('click', this.mainDom, '.WeaDoc-FileViewItem', this.clearSelection, true);
      selectable && irrelevantArea && rightSelect && offDelegate('contextmenu', this.mainDom, '.WeaDoc-FileViewItem', this.clearSelection, true);
      wheelAssist && this.InnerScroll.removeEventListener('wheel', this.mouseWheelHandle);
      this.font.isExtra && this.font.isObserver && this.systemFontObserver.disconnect();
   }

   // 浏览器兼容判断是否支持drag API
   browserCompatible = (Browsers) => {
      let support = false,
authority = false;
      const { draggable: drag } = this.props;
      const body = document.body;
      let { browser, version } = Browsers;
      // 判断浏览器版本是否支持
      browser === 'ie' && version >= 11 && (authority = true);
      browser === 'edge' && version >= 16 && (authority = true);
      browser === 'firefox' && version >= 3.5 && (authority = true);
      browser === 'chrome' && version >= 4 && (authority = true);
      browser === 'safari' && version >= 3.1 && (authority = true);
      browser === 'opera' && version >= 12.1 && (authority = true);
      // 判断浏览器是否支持HTML5拖拽API
      drag && 'ondragstart' in body && 'ondragend' in body && 'ondragenter' in body && 'ondragover' in body &&
      'ondragleave' in body && 'ondrop' in body && (support = true);

      return authority && support;
   };

   // 初始化字体处理
   initFontHandle = () => {
      this.font.isExtra = this.isFontExtra(this.browser); // 判断是否需要额外处理字体
      if (this.font.isExtra) {
         this.font.isObserver = this.isObserverFont(this.browser);
         this.font.isObserver && this.initFontObserver();
      }
      const local = localStorage.getItem('theme-themeInfo');
      const font = local ? JSON.parse(local).themeFontSize : '12';
      return this.font.isExtra && this.font.isObserver ? `text-${font}` : null;
   };

   // 初始化字体监控
   initFontObserver = () => {
      let Observer = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
      let fontTag = document.getElementsByTagName('HEAD')[0];
      const callback = (mutationList) => {
         mutationList.forEach((i) => {
            i.addedNodes.length > 0 && i.addedNodes.forEach((i) => {
               let href = i.getAttribute('href');
               if (href && href.includes('cloudstore/resource/pc/com/font-size')) {
                  let size = href.replace('/cloudstore/resource/pc/com/font-size/', '').replace('px.css', '');
                  this.setState({ fontClass: `text-${size}` });
               }
            });
         });
      };
      this.systemFontObserver = new Observer(callback);
      this.systemFontObserver.observe(fontTag, { childList: true });
   };

   // 判断字体是否需要额外处理
   isFontExtra = (b) => {
      let flag = false;
      const { browser, version } = b;
      browser === 'ie' && (flag = true);
      browser === 'edge' && version < 17 && (flag = true);
      browser === 'firefox' && version < 68 && (flag = true);
      browser === 'chrome' && version < 6 && (flag = true);
      browser === 'safari' && version < 5 && (flag = true);
      browser === 'opera' && version < 64 && (flag = true);
      return flag;
   };

   // 判断浏览器是否兼容监控API
   isObserverFont = (b) => {
      let flag = false;
      const { browser, version } = b;
      browser === 'ie' && version >= 11 && (flag = true);
      browser === 'edge' && version >= 12 && (flag = true);
      browser === 'firefox' && version >= 14 && (flag = true);
      browser === 'chrome' && version >= 18 && (flag = true);
      browser === 'safari' && version >= 6 && (flag = true);
      browser === 'opera' && version >= 15 && (flag = true);
      return flag;
   };

   // 点击无关的地方，清除所有选中
   // clearSelection = (e) => {
   //    const { selectedKeys: selectedArray, onSelect } = this.props;
   //    const { selectedKeys } = this.state;
   //    let flag = false;    // 判断有无点中Item
   //    let path =  e.path || (e.composedPath && e.composedPath());
   //    if (path === undefined) // 兼容IE
   //    {
   //       let target = e.target;
   //       while (!flag && target.tagName !== "BODY")
   //       {
   //          let className = target.className ? target.className : "";
   //          target = target.parentNode ? target.parentNode : "";
   //          className && className.includes("WeaDoc-FileViewItem") && (flag = true);
   //          if(flag) break;
   //       }
   //    }else
   //    {
   //       for(let i = 0; i < path.length; i++)
   //       {
   //          path[i].className && path[i].className.includes("WeaDoc-FileViewItem") && (flag = true);
   //          if(flag) break;
   //       }
   //    }
   //
   //    // 当 没有点中Item & 当前有选中的 & 没按ctrl键 时，触发选中事件回调
   //    !flag && typeof onSelect === "function" && selectedArray.length > 0 && !e.ctrlKey && onSelect([], selectedKeys);
   // };
   clearSelection = (e) => {
      const { selectedKeys: selectedArray, onSelect } = this.props;
      const { selectedKeys } = this.state;
      const ctrlKey = e.originalEvent.ctrlKey;
      // 当 没有点中Item & 当前有选中的 & 没按ctrl键 时，触发选中事件回调
      typeof onSelect === 'function' && selectedArray.length > 0 && !ctrlKey && onSelect([], selectedKeys);
   };

   // MouseWheel事件
   mouseWheelHandle = (e) => {
      const { onScrollTop, onScrollEnd } = this.props;
      let parent = e.target,
flag = false;
      while (!flag && parent.tagName !== 'BODY') // 找到正确的 parent DOM
      {
         let className = parent.className ? parent.className : '';
         className && className.includes('scroller') && (flag = true);
         if (flag) break;
         else parent = parent.parentNode ? parent.parentNode : '';
      }

      if (flag) {
         const viewHeight = parent.clientHeight; // 可视区域高度
         const height = parent.scrollHeight; // 滚动内容的总高度
         const prevTop = parent.scrollTop; // 开始滚动前的距离顶部高度
         const dir = e.deltaY > 0 ? 'down' : 'up'; // 滚动方向

         // prevTop = 0 & 向上滚动 & 触发top事件
         // 滚动到最低端 & 向下滚动 & 触发end事件（包含了没有滚动条的情况）
         prevTop === 0 && dir === 'up' && typeof onScrollTop === 'function' && onScrollTop(e, 'top');
         height === viewHeight + prevTop && dir === 'down' && typeof onScrollEnd === 'function' && onScrollEnd(e, 'bottom');
      }
   };

   // 子组件读写数据
   setItemData = (param = {}) => {
      Object.keys(param).forEach((i) => {
         this.ItemData[i] = param[i];
      });
   };
   getItemData = () => this.ItemData;

   // 将selectedKeys由Object转化为Array
   tranSK = object => Object.keys(object);

   // 检查必填属性
   checkNecessaryProps = (data) => {
      // id type textname 必需
      let title = '组件< DocFileIconView /> Error data属性值： ';
      let message = '';
      !(data instanceof Array) && (message = `${title}data属性应该是个数组`);
      if (data.length > 0) {
         data.forEach((item) => {
            !item.id && (message = `${title}id是必需的`);
            !item.type && (message = `${title}type是必需的`);
            let type = typeof item.textname;
            type !== 'string' && (message = `${title}textname必须是string类型  ${type}`);
         });
      }

      if (message) {
         throw new Error(message);
      }
   };

   // 处理默认的属性值
   defaultPropsHandle = (data) => {
      this.checkNecessaryProps(data); // 检查数据中的必需项
      let length = data.length;
      for (let i = 0; i < length; i++) {
         data[i].key = data[i].id;
         data[i].selectKey = data[i].id;

         typeof data[i].isFav === 'undefined' && (data[i].isFav = false);
      }
      return data;
   };

   // editStart回调处理
   editStartHandle = (selectKey) => {
      const { editStart, isEditingSameTime, onSelect } = this.props;
      const { selectedKeys } = this.props;
      let userControl,
editing = this.state.editing;
      typeof editStart === 'function' && (userControl = editStart(selectKey)); // 触发editStart事件回调
      let result = true;

      // 是否允许同时编辑的逻辑
      if (!isEditingSameTime) {
         if (editing) {
            message.warn(getLabel(513986, '不能同时编辑多个'));
            result = false;
         } else {
            editing = true; // 如果没有用户干预，开始编辑
            userControl === false && (editing = false); // 如果有用户干预，且不允许编辑
         }
      }
      editing && typeof onSelect === 'function' && onSelect([], selectedKeys); // 如果编辑状态为 true，取消所有选中
      result = typeof userControl === 'boolean' ? userControl : result; // 根据用户控制来最终决定是否允许编辑
      this.setState({ editing });

      return result;
   };

   // onOk事件回调
   onOkHandle = (key, val) => {
      const { onOk } = this.props;
      let userControl;
      typeof onOk === 'function' && (userControl = onOk(key, val));
      (userControl === true || userControl === undefined) && this.setState({ editing: false }); // 允许提交时，editing置为false
      return userControl;
   };

   // onCancel事件回调
   onCancelHandle = (key) => {
      const { onCancel } = this.props;
      typeof onCancel === 'function' && onCancel(key);
      this.setState({ editing: false });
   };

   // onChange事件回调
   onChangeHandle = (key, val) => {
      const { onChange } = this.props;
      let userControl;
      typeof onChange === 'function' && (userControl = onChange(key, val));
      return userControl;
   };

   // onFav事件回调
   onFavHandle = (selectKey) => {
      const { onFav } = this.props;
      typeof onFav === 'function' && onFav(selectKey);
   };

   // 选中事件回调
   onSelectHandle = (key, e) => {
      const { selectable, onSelect } = this.props;
      const { selectedKeys } = this.state;
      let newSelectedKeys = {};
      let current = { [key]: selectedKeys[key] ? selectedKeys[key] : false }; // 当前操作的key及其操作前的选中状态
      if (selectable) {
         newSelectedKeys = this.selectFileHandle(key, e);// 处理 文件/文件夹 的选中逻辑
         // 最新的keys和当前操作key的情况当做传入参数【编辑时不可选中】
         typeof onSelect === 'function' && !this.state.editing && onSelect(newSelectedKeys, current);
      }
   };

   // 处理文件/文件夹的选中逻辑
   selectFileHandle = (key, e) => {
      const { selectedKeys: selectedArray, selectMode } = this.props;
      const { selectedKeys } = this.state;
      const prevSelection = selectedKeys[key] ? selectedKeys[key] : false; // 操作之前的选中状态
      let newSelectedKeys;

      // 默认模式
      const ModeDefaultFunction = () => {
         let newSelectedKeys = { ...selectedKeys };
         if (prevSelection) {
            delete newSelectedKeys[key];
         } else {
            newSelectedKeys[key] = true;
         }
         return newSelectedKeys;
      };

      // 模式1
      const ModeOneFunction = () => {
         let length = selectedArray.length;
         let newSelectedKeys = {};

         const clickLeft = () => {
            // 判断点击前的选中状态，操作selectedKeys即可。
            if (prevSelection) {
               newSelectedKeys = { ...selectedKeys };
               e.ctrlKey && delete newSelectedKeys[key];
               !e.ctrlKey && length > 1 && (newSelectedKeys = { [key]: true });
               !e.ctrlKey && length === 1 && delete newSelectedKeys[key];
            } else if (length > 0) // 在选中多个时，判断有无按ctrl键
               {
                  e.ctrlKey && (newSelectedKeys = { ...selectedKeys, [key]: true });
                  !e.ctrlKey && (newSelectedKeys = { [key]: true });
               } else {
                  newSelectedKeys = { [key]: true };
               }
         };

         const clickRight = () => {
            if (length > 0) // 在有选中的情况下
            {
               !prevSelection && (newSelectedKeys = { [key]: true }); // 点击了没选中的 - 取消之前的选中，只选中当前点击的
               prevSelection && (newSelectedKeys = { ...selectedKeys }); // 点击了被选中的某一个 - 什么也不做
            } else {
               newSelectedKeys = { [key]: true }; // 没有任何选中的情况下，点击哪个就选中哪个
            }
         };

         if (e.button === 0) // 点击左键
         {
            clickLeft();
         } else if (e.button === 2) // 点击右键
         {
            clickRight();
         }

         return newSelectedKeys;
      };

      switch (selectMode) {
         case 0:
            newSelectedKeys = ModeDefaultFunction();
            break;
         case 1:
            newSelectedKeys = ModeOneFunction();
            break;
         default:
            newSelectedKeys = ModeDefaultFunction();
            break;
      }

      return this.tranSK(newSelectedKeys); // 返回array
   };

   // Item点击事件
   onClickHandle = (selectKey, e) => {
      const { onClick } = this.props;
      typeof onClick === 'function' && onClick(selectKey, e);
   };

   // Item双击事件
   onDoubleClickHandle = (selectKey, e) => {
      const { onDoubleClick } = this.props;
      typeof onDoubleClick === 'function' && onDoubleClick(selectKey, e);
   };

   // dragSuccess回调
   dragSuccessHandle = (to, keys) => {
      const { draggable, dragSuccess } = this.props;
      draggable && typeof dragSuccess === 'function' && dragSuccess(to, keys); // 传参 from. to, keys
   };

   // onScroll滚动回调
   onScrollHandle = (e) => {
      const { onScroll, onScrollTop, onScrollEnd, offsetTop, offsetBottom } = this.props;
      const viewHeight = e.target.clientHeight; // 可视区域高度
      const height = e.target.scrollHeight; // 滚动内容的总高度
      const top = e.target.scrollTop;
      const dir = this.scroll.prevScroll > top ? 'up' : 'down'; // 滚动方向
      const isBottom = height <= viewHeight + top + offsetBottom;
      const isTop = top <= offsetTop;

      typeof onScroll === 'function' && onScroll(e);
      isBottom && !this.scroll.prevBottom && dir === 'down' && typeof onScrollEnd === 'function' && onScrollEnd(e, 'down');
      isTop && !this.scroll.prevTop && dir === 'up' && typeof onScrollTop === 'function' && onScrollTop(e, 'up');

      this.scroll = { prevScroll: top, prevBottom: isBottom, prevTop: isTop };
   };


   // 新建文件夹
   newFolder = () => {
      let result = { flag: false, msg: '', metaData: {} };
      if (this.state.editing) {
         result.msg = getLabel(513987, '请完成当前编辑');
      } else {
         result.flag = true;
         result.metaData = {
            id: this.getRandomID('folder', 6),
            type: 'folder',
            textname: getLabel(513708, '新建目录'),
            editing: true,
         };
         this.setState({ editing: true });
         const { onSelect } = this.props;
         const { selectedKeys } = this.state;
         typeof onSelect === 'function' && onSelect([], selectedKeys); // 取消所有选中
      }
      return result;
   };

   // 重命名【模拟点击】
   reNameFile = (key) => {
      const { editMode } = this.props;
      const ItemDOM = this.ChildrenRefs[key].ItemDOM;
      editMode === 0 && ItemDOM.querySelector('i.Edit-Icon').click(); // 模拟点击
      editMode === 1 && ItemDOM.querySelector('.textname').click();
   };

   // 获取6位随机ID
   getRandomID = (prefix, n) => `${prefix}_${getRandomString(n)}`;

   // 获取当前选中的keys
   getSelectKeys = () => this.state.selectedKeys;

   // 获取当前选中的DOM
   getSelectDOM = () => this.props.selectedKeys.map(i => this.ChildrenRefs[i].ItemDOM);


   render() {
      const { data, iconType, selectable, rightSelect, editable, editMode, collectable, selectMode, selectedKeys, titleType, titlePosition,
         textCharLen, textByteLen, draggable, scrollHeight, loadMore, pageLoading, pageEnd, namingRules, className, style,
         itemClass, itemStyle, scrollInnerClass, scrollInnerStyle } = this.props;
      const datas = this.defaultPropsHandle(data); // 处理默认的属性值
      const canDrag = this.dragSupport && !this.state.editing ? draggable : false; // 判断是否允许拖拽

      return (
         <div id="WeaDocument-FileIconView" className={className || ''} style={style} ref={(e) => {
 this.mainDom = e; 
}}>
            <WeaNewScroll ecId={`${this && this.props && this.props.ecId || ''}_WeaNewScroll@sh6m4j`} height={typeof scrollHeight === 'number' ? scrollHeight : null} onScroll={this.onScrollHandle} style={{ height: '100%' }}>
               {
                  !this.dragSupport && draggable && <Alert ecId={`${this && this.props && this.props.ecId || ''}_Alert@nwzsah`} type="warning"
                    message={getLabel(514141, '功能提示')}
                    closable
                    showIcon
                    description={getLabel(514142, '您当前浏览器版本过低，不支持文件拖拽功能。请更换主流浏览器（Chrome、Firefox、Edge等）或者升级 IE 版本，以获得更好的体验。')}
                  />
               }
               <div className={`WeaDoc-innerScroll ${loadMore ? (pageEnd ? 'noMore' : 'loadPage') : ''} ${scrollInnerClass || ''}`}
                 style={scrollInnerStyle || {}}
                 ref={(e) => {
 this.InnerScroll = e; 
}}
               >
                  {
                     datas.length > 0 && datas.map(item => (
                        <WeaDocFileItem ecId={`${this && this.props && this.props.ecId || ''}_WeaDocFileItem@0o6pzh@${item.key}`}
                          selectable={selectable}
                          selectMode={selectMode}
                          editable={editable}
                          collectable={collectable}
                          rightSelect={rightSelect}
                          {...item}
                          itemClass={itemClass}
                          itemStyle={itemStyle}
                          draggable={canDrag}
                          namingRules={namingRules}
                          editMode={editMode}
                          iconType={iconType}
                          browser={this.browser} // 浏览器及版本
                          ref={(e) => {
 this.ChildrenRefs[item.key] = e; 
}}
                          font={{ fClass: this.state.fontClass, ...this.font }} // 字体相关
                          selected={selectedKeys.includes(item.key)}
                          textCharLen={textCharLen}
                          textByteLen={textByteLen}

                          titleType={titleType}
                          titlePosition={titlePosition}
                          editStart={this.editStartHandle}
                          onOk={this.onOkHandle}
                          onCancel={this.onCancelHandle}
                          onChange={this.onChangeHandle}
                          onFav={this.onFavHandle}
                          onClick={this.onClickHandle}
                          onDoubleClick={this.onDoubleClickHandle}
                          onSelect={this.onSelectHandle}
                          dragSuccess={this.dragSuccessHandle}
                          getSelectKeys={this.getSelectKeys} // 用于子组件获取当前选中keys
                          getSelectDOM={this.getSelectDOM} // 用于子组件获取多选拖动的样式
                          getItemData={this.getItemData} // 由于子组件存取公共数据
                          setItemData={this.setItemData}
                        />
                     ))
                  }
                  {
                     loadMore
                     ?
                     <React.Fragment ecId={`${this && this.props && this.props.ecId || ''}_undefined@a9bsab`}>
                        <Spin ecId={`${this && this.props && this.props.ecId || ''}_Spin@mwp6t2`} spinning={pageLoading} tip={getLabel(514139, '正在读取数据')} className="Spin" size="large" />
                        { pageEnd ? <div className="no-MoreData">------------&nbsp;&nbsp;&nbsp;{getLabel(514140, '这 里 是 底 线')}&nbsp;&nbsp;&nbsp;------------</div> : null }
                     </React.Fragment>
                     : null
                  }
               </div>
               { datas.length === 0 ? <WeaDocNoData ecId={`${this && this.props && this.props.ecId || ''}_WeaDocNoData@i3uzuw`} icon={2} text={getLabel(514012, '暂无文件')} /> : null }
            </WeaNewScroll>
         </div>
      );
   }
}


export default WeaDocFileIconView;
